/**
 * Arbiter
 */

import misc.Player;
import boardtiles.*;
import activepieces.*;
import structs.*;

import java.util.*;

public class Arbiter {

    /**
     * This function is to be used in Cities and Knights to figure out
     * @param boardRoot a tile on the board
     * @param players array of players
     */
    public void processBarbarianAttack(Tile boardRoot, Player[] players) {
        int numCities = countCities(players);
        //not finished
    }

    public static Tile createRandomizedStandardBoard() {
        //build adjacency matrix
            //parse the file and turn it into matrix
        //use matrix to build the graph with appropriate tiles

        return null;
    }

    private static String produceString(char c, int length) {
        String result = "";
        for (int i = 0; i < length; i++) {
            result += "" + c;
        }
        return result;
    }

    private static boolean[] turnStringToBits(String s) {
        boolean[] result = new boolean[s.length()];
        for (int i = 0; i < s.length(); i++) {
            boolean currentValue = false;
            if (s.charAt(i) == '1') {
                currentValue = true;
            }
            result[i] = currentValue;
        }
        return result;
    }

    private static int countCities(Player[] players) {
        int cityCount = 0;
        for (int i = 0; i < players.length; i++) {
            cityCount += countCities(players[i]);
        }
        return cityCount;
    }

    private static int countCities(Player player) {
        int cityCount = 0;
        Iterator<PlayerStructure> iter = player.getStructures().iterator();
        while (iter.hasNext()) {
            PlayerStructure currentStructure = iter.next();
            if (currentStructure instanceof City) {
                cityCount++;
            }
        }
        return cityCount;
    }


    /**
     * Function will distribute resources to the appropriate players given a
     * board and the number that rolled.
     * @param boardRoot A tile on the board
     * @param players Array of players
     * @param productionNumber the number that rolled determining production
     */
    public static void distributeResources(Tile boardRoot,
            Player[] players, int productionNumber) {
        distributeResources(boardRoot, players, productionNumber, new LinkedList<Tile>());
    }

    private static void distributeResources(Tile boardTile,
            Player[] players, int productionNumber, List<Tile> alreadyVisited) {
        if (boardTile instanceof ResourceTile &&
                ((ResourceTile)boardTile).getProductionNumber() == productionNumber) {
            distributeResources((ResourceTile)boardTile, players);
        }
        alreadyVisited.add(boardTile);
        Tile[] neighbors = boardTile.getNeighbors();
        for (int i = 0; i < neighbors.length; i++) {
            if (neighbors[i] != null && !alreadyVisited.contains(neighbors[i])) {
                distributeResources(neighbors[i], players, productionNumber, alreadyVisited);
            }
        }
    }

    private static void distributeResources(ResourceTile boardTile, Player[] players) {
        for (int i = 0; i < players.length; i++) {
            int productionAmount = playerProductionLevel(boardTile, players[i]);
            for (int j = 0; j < productionAmount; j++) {
                players[i].addResource(boardTile.getResource());
            }
        }
    }

    private static int playerProductionLevel(Tile boardTile, Player player) {
        LinkedList<PlayerStructure> buildings = player.getStructures();
        int productionLevel = 0;

        Iterator<PlayerStructure> iterator = buildings.iterator();
        while (iterator.hasNext()) {
            PlayerStructure currentBuilding = iterator.next();
            Vertex currentVertex = currentBuilding.getLocation();
            if (currentBuilding instanceof ProductionStructure &&
                    (currentVertex.t1 == boardTile ||
                    currentVertex.t2 == boardTile ||
                    currentVertex.t3 == boardTile)) {
                productionLevel += ((ProductionStructure)currentBuilding).getProductionPower();
            }
        }

        return productionLevel;

    }
}
